#include "ws2812.h"
#include "stdlib.h"
p_ws2812 temp_ws2812; //临时变量，用于存储当前操作的ws2812对象
uint8_t WS2812_Init(p_ws2812 ws2812, uint16_t num)
{
    temp_ws2812 = ws2812;
    ws2812->num = num;
    // ws2812->buff_len = RESET_PULSE_NUM + num*WS2812_SINGLE_DATA_LEN;
    ws2812->buff = (uint16_t*)malloc(sizeof(uint16_t) * (RESET_PULSE_NUM + num*WS2812_SINGLE_DATA_LEN));
    if(ws2812->buff ==NULL) return 1; //返回1表示申请内存失败
    memset(ws2812->buff,0,sizeof(uint16_t)*RESET_PULSE_NUM); //将reset字段赋值为0
    ws2812->finish_flag = true; //标志数据传输完成,可以开始下一次传输
    return 0; //返回0表示初始化成功
}

uint8_t WS2812_UnInit(p_ws2812 ws2812)
{
    free(ws2812->buff);
    ws2812->num = 0;
    return 0;
}

uint8_t WS2812_ClearAllPixel(p_ws2812 ws2812)
{
    uint16_t * color_buff = ws2812->buff + RESET_PULSE_NUM; //取出pixel颜色字段的地址
    for(uint16_t i = 0; i < ws2812->num; i++)
    {
        for(uint16_t j = 0; j < WS2812_SINGLE_DATA_LEN; j++)
        {
            // if((i*WS2812_SINGLE_DATA_LEN + j) >= ws2812->buff_len)return 1;
            color_buff[i * WS2812_SINGLE_DATA_LEN + j] = ZERO_PULSE; // 全部赋值为0bit码的CCR
        }
    }
    return 0;
}

uint8_t WS2812_SetPixel(p_ws2812 ws2812, uint16_t num, uint8_t R, uint8_t G, uint8_t B)
{
    if(num >= ws2812->num)return 1; // 超过设定的led数量
    uint16_t * color_buff = ws2812->buff + RESET_PULSE_NUM + num*WS2812_SINGLE_DATA_LEN; //取出对应pixel的颜色字段的地址
    for(uint8_t i = 0; i < 8;i++)
    {
        if(G >> i & 0x01) color_buff[7-i] = ONE_PULSE;
        else color_buff[7-i] = ZERO_PULSE;
    }
    for(uint8_t i = 0; i < 8;i++)
    {
        if(R >> i & 0x01) color_buff[15-i] = ONE_PULSE;
        else color_buff[15-i] = ZERO_PULSE;
    }
    for(uint8_t i = 0; i < 8;i++)
    {
        if(B >> i & 0x01) color_buff[23-i] = ONE_PULSE;
        else color_buff[23-i] = ZERO_PULSE;
    }
    return 0;
}

#include "ws2812_port.h"
uint8_t ws2812_Send_Data(p_ws2812 ws2812)
{
    HAL_StatusTypeDef status = HAL_OK;
    if(temp_ws2812->finish_flag == true) //上次已经传输完成了
    {
        status = WS2812_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_2,(const uint32_t*)ws2812->buff,
                    RESET_PULSE_NUM + ws2812->num *WS2812_SINGLE_DATA_LEN);
        temp_ws2812->finish_flag = false;
    }
    return (uint8_t)status;
}

void WS2812_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
   WS2812_TIM_PWM_Stop_DMA(&htim3,TIM_CHANNEL_2);
   temp_ws2812->finish_flag = true;
}
